﻿using System;
using System.Collections;
using System.Collections.Generic;
using Entidades;
using Ext.Net;
using ModuloSoporte.Excepciones;
using PhantomDb.Entidades;
using Siscont.Contabilidad;
using Siscont.Contabilidad.Excepciones;
using WebHelper;
using System.Linq;

namespace IU.Contabilidad.PlanCuentas
{
    /// <summary>
    /// Árbol de cuentas.
    /// FALTA:
    /// * Refresh que solo actualice el árbol.
    /// * Altas y modificaciones.
    /// </summary>
    public partial class ArbolGen : System.Web.UI.Page
    {
        private const string NodoAttribute = "Idcuenta";
        private const string NodoString = "{$Idcuenta}. {$Descripcion}";

        protected void Page_Load(object sender, EventArgs e)
        {
            if (!X.IsAjaxRequest)
            {
                Session["cod-cuenta.old"] = 0; // Cuenta anteriormente seleccionada
                Session["cod-cuenta"] = null;  // Cuenta seleccionada
                WindowDelete.Hide(); // BUGFIXER
                VentanaAM.Hide(); // BUGFIXER

                /* Bugfixer: al hacer varios clicks en aceptar te agrega muchas veces un mov. */
                Session["ArbolGen_CanClick"] = true;
            }

            this.ControlArbol1.AlSeleccionarNodo += new IU.Generico.SelectedNodeDelegate(ControlArbol1_AlSeleccionarNodo);
            this.GenerarArbol();
            this.ControlArbol1.OnShow();

            /* VENTANA DE A/M DE CUENTAS */
            this.CargarDatosEnCombos();
        }

        void GenerarArbol()
        {
            this.ControlArbol1.Raiz = new NodoLite("Plan de cuentas", NodoAttribute, NodoString);
            foreach (var c in ContabilidadGlobal.Admin.ObtenerCuentas())
            {
                var cuenta = new Cuenta(c);
                AgregarCuentaEnArbol((NodoLite)this.ControlArbol1.Raiz, cuenta, cuenta.Nivel);
            }
        }

        void ControlArbol1_AlSeleccionarNodo(string nodo)
        {
            try
            {
                /* Si selecciono una cuenta... */
                if (nodo.Contains("."))
                {
                    int oldCod = (int)Session["cod-cuenta.old"];
                    int cod = int.Parse(nodo.Substring(0, nodo.IndexOf(".")));

                    if (oldCod != cod)
                    {
                        Entity_cuenta cuenta = new Entity_cuenta
                        {
                            Idcuenta = cod.ToString(),
                            Ejercicio_codejercicio = (int)ContabilidadGlobal.Admin.CodEjercicio,
                            Ejercicio_empresa_idempresa = ContabilidadGlobal.Admin.CodEmpresa
                        };

                        cuenta = (Entity_cuenta)CapaDatos.Datos.Manejador[typeof(Entity_cuenta)].Cargar((object)cuenta);

                        Session["cod-cuenta"] = cuenta;

                        TextFieldCod.Text = cod.ToString();
                        TextFieldNom.Text = cuenta.Descripcion;
                        TextFieldImputable.Text = cuenta.Imputable ? "Si" : "No";
                        TextFieldColumnaImp.Text = cuenta.Columnaimpresion.ToString();
                        if (cuenta.Imputable)
                        {
                            if (cuenta.Unidad_idunidad > 0)
                            {
                                Entity_unidad unidad = new Entity_unidad
                                {
                                    Empresa_idempresa = ContabilidadGlobal.Admin.CodEmpresa,
                                    Idunidad = cuenta.Unidad_idunidad
                                };

                                unidad = (Entity_unidad)CapaDatos.Datos.Manejador[typeof(Entity_unidad)].Cargar((object)unidad);

                                TextFieldUnidad.Text = string.Format("{0} - {1}", unidad.Idunidad, unidad.Descripcion);
                                TextFieldUnidad.Show();
                            }
                            else
                            {
                                TextFieldUnidad.Hide();
                            }
                        }
                        else
                        {
                            TextFieldUnidad.Hide();
                        }

                        if (FormPanelDetalles.Hidden)
                            FormPanelDetalles.Show();

                        if (cuenta.Editable)
                            ButtonModificar.Show();
                        else
                            ButtonModificar.Hide();
                        //ButtonEliminar.Show();

                        Session["cod-cuenta.old"] = cod;
                    }
                }
                else
                {
                    FormPanelDetalles.Hide();
                    ButtonModificar.Hide();
                    //ButtonEliminar.Hide();
                    Session["cod-cuenta.old"] = 0;
                    Session["cod-cuenta"] = null;
                }
            }
            catch
            {
                Session["cod-cuenta.old"] = 0;
                Session["cod-cuenta"] = null;
                ButtonModificar.Hide();
                //ButtonEliminar.Hide();
            }
        }

        private void AgregarCuentaEnArbol(NodoLite raiz, Cuenta cuenta, int nivel)
        {
            try
            {
                if (nivel == 0)
                {
                    if (cuenta.Imputable)
                    {
                        raiz.AgregarEntidad(cuenta.Datos);
                    }
                    else
                    {
                        var nodo = new NodoLite(cuenta.Nombre);
                        nodo.AtributoId = "Idcuenta";
                        nodo.LineaDisplay = NodoString;
                        raiz.AgregarHijo(nodo);
                    }
                }
                else
                {
                    foreach (var n in raiz.Hijos)
                    {
                        /* Si mi cuenta va en la encontrada */
                        string cod = n.Nombre.Substring(0, n.Nombre.IndexOf('.'));
                        if (cuenta.Datos.Idcuenta.StartsWith(cod))
                        {
                            AgregarCuentaEnArbol((NodoLite)n, cuenta, nivel - 1);
                            return;
                        }
                        /* Si la encontrada va en mi cuenta */
                        else if (cod.StartsWith(cuenta.Datos.Idcuenta))
                        {
                            n.Nombre = cuenta.Nombre; // Cambio su nombre, y la agrego adentro de la mia
                            var nuevoC = new Entity_cuenta { Idcuenta = cod, Ejercicio_codejercicio = cuenta.Datos.Ejercicio_codejercicio, Ejercicio_empresa_idempresa = cuenta.Datos.Ejercicio_empresa_idempresa };
                            Cuenta nuevoHijo = new Cuenta((Entity_cuenta)CapaDatos.Datos.Manejador[typeof(Entity_cuenta)].Cargar(nuevoC));
                            AgregarCuentaEnArbol((NodoLite)n, nuevoHijo, 0);
                            return;
                        }
                        
                    }

                    AgregarCuentaEnArbol(raiz, cuenta, 0);
                }

            }
            catch(Exception ex)
            {
                UIHelper.MostrarExcepcionSimple(ex, "Error");
            }
        }

        private NodoLite GenerarNodosAnidados(List<Entity_cuenta> cuentas, AbstractNodo nodoRaiz)
        {
            try
            {
                Cuenta cuenta;
                int nivel = 0;
                bool imputable = false;
                NodoLite retorno = null;
                NodoLite raiz = null;
                NodoLite nodo;
                foreach (var c in cuentas)
                {
                    cuenta = new Cuenta(c);
                    nodo = new NodoLite(cuenta.Nombre);
                    nodo.AtributoId = "Idcuenta";
                    nodo.LineaDisplay = NodoString;
                    if (raiz == null)
                    {
                        raiz = nodo;
                        retorno = raiz;
                        nivel = cuenta.Nivel;
                    }
                    else if (nivel < cuenta.Nivel && cuenta.Imputable == false) // Si hay un cambio de nivel
                    {
                        raiz.AgregarHijo(nodo);
                        raiz = nodo;
                        nivel = cuenta.Nivel;
                        imputable = cuenta.Imputable;
                    }
                    else
                    {
                        raiz.AgregarEntidad(c);
                        nivel = cuenta.Nivel;
                    }
                }

                return retorno;
            }
            catch (Exception ex)
            {
                UIHelper.MostrarExcepcionSimple(ex, "Error al generar nodos.");
                return null;
            }
        }

        [DirectMethod]
        protected void ButtonAgregar_Click(object sender, DirectEventArgs e)
        {
            this.FormNumberFieldCod.ReadOnly = false;
            this.FormNumberFieldColumn.Value = 4;
            
            Session["ArbolGen_CanClick"] = true; /* Bugfix */
            Session["ArbolGen_Modificar"] = false;
            VentanaAM.Show();
            CargarDatosEnCombos();
        }

        [DirectMethod]
        protected void ButtonModificar_Click(object sender, DirectEventArgs e)
        {
            // Modificar cuenta
            var cuenta = (Entity_cuenta)Session["cod-cuenta"];
            if (cuenta != null)
            {
                this.FormNumberFieldCod.Value = int.Parse(cuenta.Idcuenta);
                this.FormTextFieldCapi.Text = cuenta.Capitulo;
                this.FormTextFieldDescripcion.Text = cuenta.Descripcion;
                this.FormNumberFieldColumn.Value = cuenta.Columnaimpresion;
                this.FTextFieldImputable.Text = cuenta.Imputable ? "Si" : "No";

                this.FormNumberFieldCod.ReadOnly = true;

                Session["ArbolGen_CanClick"] = true; /* Bugfix */
                Session["ArbolGen_Modificar"] = true;
                VentanaAM.Show();
                CargarDatosEnCombos();
            }
        }

        [DirectMethod]
        protected void ButtonUpdate_Click(object sender, DirectEventArgs e)
        {
            // Actualizar árbol
            this.ControlArbol1.ResetearArbol();
            //Response.Redirect("ArbolGen.aspx");
        }

        [DirectMethod]
        protected void ButtonEliminar_Click(object sender, DirectEventArgs e)
        {
            var cuenta = (Entity_cuenta)Session["cod-cuenta"];
            if (cuenta != null)
            {
                LabelEstado.Text = string.Format("¿Desea eliminar la cuenta {0}?", cuenta.Idcuenta);
                WindowDelete.Hidden = false;
                WindowDelete.Show();
            }
        }

        protected void CargarDatosEnCombos()
        {
            try
            {
                StoreComboMov.DataSource = ContabilidadGlobal.Admin.ObtenerListaUnidades();
                StoreComboMov.DataBind();
            }
            catch (Exception ex)
            {
                UIHelper.MostrarExcepcionSimple(ex, "Error al cargar las unidades");
            }
        }

        /// <summary>
        /// Si aceptas la eliminación de una cuenta?
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        [DirectMethod]
        protected void ButtonAceptar_Click(object sender, DirectEventArgs e)
        {
            try
            {
                var cuenta = (Entity_cuenta)Session["cod-cuenta"];
                CapaDatos.Datos.Manejador[typeof(Entity_cuenta)].Eliminar(cuenta);
            }
            catch (Exception ex)
            {
                UIHelper.MostrarExcepcionSimple(ex, "Error");
            }
        }

        /// <summary>
        /// Aceptar alta/modificación.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        [DirectMethod]
        protected void Form_BotonAceptar_Click(object sender, DirectEventArgs e)
        {
            try
            {
                if ((bool)Session["ArbolGen_CanClick"])
                {
                    /* Obtener datos de la ventana */
                    var dict = JSON.Deserialize<Dictionary<string, string>>(e.ExtraParams["values"]);
                    var cuenta = new Entidades.Entity_cuenta
                    {
                        Idcuenta = dict["FormNumberFieldCod"],
                        Columnaimpresion = int.Parse(dict["FormNumberFieldColumn"]),
                        Descripcion = dict["FormTextFieldDescripcion"],
                        Ejercicio_codejercicio = (int)ContabilidadGlobal.Admin.CodEjercicio,
                        Ejercicio_empresa_idempresa = ContabilidadGlobal.Admin.CodEmpresa,
                        //Imputable = int.Parse(dict["ComboBoxImputable_Value"]) != 0,
                        Imputable = !dict["FTextFieldImputable"].Equals("no", StringComparison.OrdinalIgnoreCase),
                        Capitulo = dict["FormTextFieldCapi"],
                        Editable = true,
                        Unidad_idunidad = 0
                    };
                    var db = CapaDatos.Datos.Manejador[typeof(Entity_cuenta)];

                    /* Work */
                    if (!(bool)Session["ArbolGen_Modificar"]) // ALTA
                    {
                        if (db.Existe(cuenta))
                            throw new ExcepcionValorInvalido(
                                string.Format("La cuenta \"{0}\" ya existe.", 
                                cuenta.Idcuenta));

                        db.Insertar(cuenta);
                    }
                    else // MODIFICACIÓN
                    {
                        if (!cuenta.Editable)
                            throw new Excepcion("La cuenta modificada no es editable.");

                        CustomValue[] valores = new CustomValue[] 
                        {
                            //new CustomValue("Idcuenta", cuenta.Idcuenta),
                            new CustomValue("Columnaimpresion", cuenta.Columnaimpresion),
                            new CustomValue("Descripcion", cuenta.Descripcion),
                            new CustomValue("Imputable", cuenta.Imputable),
                            new CustomValue("Capitulo", cuenta.Capitulo)
                        };
                        db.Modificar(cuenta, valores);
                        Session["cod-cuenta"] = cuenta;
                    }
                }

                this.CerrarVentana();
                Session["ArbolGen_CanClick"] = false; /* Bugfix */
            }
            catch (ExcepcionValorInvalido ex)
            {
                UIHelper.MostrarExcepcionSimple(ex, "Valor inválido");
            }
            catch (Excepcion ex)
            {
                UIHelper.MostrarExcepcionSimple(ex, "Error");
            }
#if !DEBUG
            catch
            {
#else
            catch(Exception ex2)
            {
                UIHelper.MostrarExcepcionSimple(ex2, "Error");
#endif
                this.CerrarVentana();
                Session["ArbolGen_CanClick"] = false; /* Bugfix */
            }
        }

        [DirectMethod]
        protected void Form_BotonCancelar_Click(object sender, DirectEventArgs e)
        {
            // this.CerrarVentana(); // Ahora ejecuto el cierre por client-side
        }

        /// <summary>
        /// Oculta la ventana y resetea todos sus campos.
        /// </summary>
        private void CerrarVentana()
        {
            VentanaAM.Hide();
        }
    }
}
